/*
 * main.cpp
 *
 *  Created on: 23/10/2012
 *      Author: emmanuel
 */
#include <unistd.h>

#include <cstdlib>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <iostream>
#include <string.h>
#include <stddef.h>
#include "ProcesadordeTareas.h"
#include "Comunes/Palabra.h"

using namespace std;
using namespace palabra;

void printEncabezado(string mensaje) {

	cout << "                      ";
	cout << mensaje;
	cout << "                      \n";

	cout << "                      ";
	for (unsigned int i = 0; i < mensaje.length(); i++){
		cout << "=";
	}
	cout << "                      \n\n";


}

int get_Opcion(string s){
	istringstream buffer(s);
	int valor;
	buffer >> valor;
	return valor;
}

void limpiarPantalla(){
	for (int i = 0; i < 50; i++){
		cout << "" << endl;
	}
}

void printMenuPrincipal() {

		limpiarPantalla();

        printEncabezado("MENU PRINCIPAL");

        cout << "   1- Terminos\n";
        cout << "   2- Frases\n";
        cout << "   3- Estadisticas y Reportes\n";
        cout << "   4- Salir\n";

        cout << '\n';
        cout << " ";
        cout << "Su eleccion: ";
}


void printMenuTerminos() {

		limpiarPantalla();
        printEncabezado("MENU TERMINOS");
        cout << "   1- Buscar un Termino\n";
        cout << "   2- Reportar estructura de Terminos \n";
        cout << "   3- Reportar listado de terminos ordenados \n";
        cout << "   4- Salir\n";
        cout << '\n';
        cout << " ";
        cout << "Su eleccion: ";
}

void printMenuFrases() {

		limpiarPantalla();
        printEncabezado("MENU FRASES");
        cout << "   1- Insertar\n";
        cout << "   2- Eliminar\n";
        cout << "   3- Modificar\n";
        cout << "   4- Buscar\n";
        cout << "   5- Reportar listado de frases\n";
        cout << "   6- Salir\n";
        cout << '\n';
        cout << " ";
        cout << "Su eleccion: ";
}

void printMenuEstadisticas() {

		limpiarPantalla();
        printEncabezado("MENU ESTADISTICAS Y REPORTES");
        cout << "   1- Cantidad de términos promedio por frase\n";
        cout << "   2- Tasa de fallos de términos\n";
        cout << "   3- Lista de términos no encontrados \n";
        cout << "   4- Ranking de los n términos mas populares\n";
        cout << "   5- Salir\n";
        cout << '\n';
        cout << " ";
        cout << "Su eleccion: ";
}

void printEsperarOpcionSalir(){
	string op;
	cout << '\n';
	cout << "Presione ENTER para continuar ";

}


void printResultadoOpcion(string opcion, string resultado){
	string op;
	limpiarPantalla();
    printEncabezado(opcion);
    cout << endl;
    cout << endl;
    cout << resultado << endl;
    cout << endl;
	printEsperarOpcionSalir();
	getline(cin, op);
}

void printEstructuraDirectorios(){
	string resultado = "";
	resultado.append("Inicializacion exitosa => Estructura de directorios creada:\n");
	resultado.append("===========================================================\n");
	resultado.append("DIRECTORIO RAIZ->\n");
	resultado.append("  ORDEN_DICC->\n");
	resultado.append("    particiones->\n");
	resultado.append("    fusion->\n");
	resultado.append("       etapa1->\n");
	resultado.append("       etapa2->\n");
	resultado.append("           ....\n");
	resultado.append("       ......\n");
	resultado.append("  HASH_FRASES->\n");
	resultado.append("    tabla\n");
	resultado.append("    cubos\n");
	resultado.append("  ARBOLBMAS->\n");
	resultado.append("  DEFAULT_ARBOL->\n");
	resultado.append("     ARBOLBMAS->\n");
	resultado.append("        Diccionario_en_Arbol_Configuracion\n");
	resultado.append("        Diccionario_en_Arbol_FrontCoding\n");
	resultado.append("        Diccionario_en_Arbol_Nodos\n");
	resultado.append("  informe_particiones.txt\n");
	resultado.append("  informe_merge.txt\n");
	printResultadoOpcion("INICIALIZACION DE DIRECTORIOS Y ESTRUCTURAS", resultado);
}

void MenuTerminos(ProcesadordeTareas & procesador){
	int option;
    string op;
    string termino;
    string resultado;
    int logout = 0;
    try{
        while (logout != 1) {
        	printMenuTerminos();
        	getline(cin, op);
        	option = get_Opcion(op);
        	switch (option) {
				case 1: //Buscar un termino en el arbol
					cout << endl;
					cout << "Inserte el termino a buscar: " << endl;
					getline(cin,termino);
					resultado = "";
					resultado.append("Término buscado: " +  termino);
					resultado.append("\n\n");
					resultado.append(procesador.buscar_termino(termino));
					resultado.append("\n\n");
					resultado.append("OBS: Si el termino buscado no es encontrado devuelve el siguiente");
					printResultadoOpcion("BUSQUEDA DE TERMINOS", resultado);
					break;
				case 2: //Reportar arbol con Terminos insertados
					procesador.reporte_estructura_arbol();
					resultado = "";
					resultado.append("Se generó un archivo con la estructura del arbol en : " + procesador.get_path_arbol() + ".txt");
					printResultadoOpcion("REPORTE DE LA ESTRUCTURA DEL ARBOL", resultado);
					break;
				case 3: //Reportar listado de terminos ordenados
					procesador.reporte_terminos_ordenados();
					resultado = "";
					resultado.append("Se generó un archivo con todos los terminos ordenados en : " + procesador.get_path_arbol() + "_listado.txt");
					printResultadoOpcion("REPORTE DE TERMINOS INSERTADOS", resultado);
					break;
				case 4:
					logout = 1;
					break;
				default:
					break;
        	}
        }
    }catch(exception &e){
		string resultado = "";
		resultado.append("Se produjo un error al procesar su solicitud.");
		resultado.append("\n");
		resultado.append("DESCRIPCION: " + (string)e.what());
		printResultadoOpcion("ATENCION!!!", resultado);
		printMenuTerminos();
    }
}

void MenuFrases(ProcesadordeTareas & procesador){
	int option;
	string resultado;
	string op;
	string termino;
	int logout = 0;
	string apellido_autor = "";
	string nombre_autor = "";
	string frase = "";
	string strid = "";
	int id = 0;
	try{
        while (logout != 1) {
        	printMenuFrases();
        	getline(cin, op);
        	option = get_Opcion(op);
        	switch (option) {
				case 1: //Insertar
					apellido_autor = "";
					nombre_autor = "";
					frase = "";
					strid = "";
					cout << "Inserte una frase: " << endl;
					cout << "identificador: " << endl;
					getline(cin, strid);
					cout << "apellido del autor: " << endl;
					getline(cin, apellido_autor);
					cout << "nombre del autor: " << endl;
					getline(cin, nombre_autor);
					cout << "frase: " << endl;
					getline(cin, frase);
					id = get_Opcion(strid);
					procesador.insertar_frase(id, nombre_autor, apellido_autor, frase);
					resultado = "";
					resultado.append("Frase a insertar: " +  frase);
					resultado.append("\n\n");
					resultado.append("La frase fue insertada con exito.");
					printResultadoOpcion("INSERTAR FRASE", resultado);
					break;
				case 2: //Eliminar
					id = 0;
					cout << "Identificador: "; cin >> id;
					procesador.eliminar_frase(id);
					resultado = "";
					resultado.append("Frase a eliminar: " +  frase);
					resultado.append("\n\n");
					resultado.append("La frase fue eliminada con exito.");
					printResultadoOpcion("ELIMINAR FRASE", resultado);
					break;
				case 3: //Modificar
					apellido_autor = "";
					nombre_autor = "";
					frase = "";
					strid = "";
					cout << "Inserte una frase: " << endl;
					cout << "identificador: " << endl;
					getline(cin, strid);
					cout << "apellido del autor: " << endl;
					getline(cin, apellido_autor);
					cout << "nombre del autor: " << endl;
					getline(cin, nombre_autor);
					cout << "frase: " << endl;
					getline(cin, frase);
					id = get_Opcion(strid);
					procesador.modificar_frase(id, nombre_autor, apellido_autor, frase);
					resultado = "";
					resultado.append("Frase a modificar: " +  frase);
					resultado.append("\n\n");
					resultado.append("La frase fue modificada con exito.");
					printResultadoOpcion("MODIFICAR FRASE", resultado);
					break;
				case 4: //Buscar
					id = 0;
					cout << "Identificador: ";
					getline(cin, strid);
					id = get_Opcion(strid);
					resultado = "";
					resultado.append("Identificador de la frase: " +  strid);
					resultado.append("\n\n");
					resultado.append("La frase fue encontrada.\n\n");
					resultado.append(procesador.buscar_frase(id));
					printResultadoOpcion("BUSCAR FRASE", resultado);
					break;
				case 5: //listado de frases
					cout << "Aguarde un instante por favor...." << endl;
					procesador.reporte_cubos();
					resultado = "";
					resultado.append("Se generó un archivo con la estructura del hash en : " + procesador.get_path_hash());
					printResultadoOpcion("REPORTE DE FRASES EN ARCHIVO", resultado);
					break;
				case 6:
					logout = 1;
					break;
				default:
					break;
        	}
        }
	}catch(exception &e){
		string resultado = "";
		resultado.append("Se produjo un error al procesar su solicitud.");
		resultado.append("\n");
		resultado.append("DESCRIPCION: " + (string)e.what());
		printResultadoOpcion("ATENCION!!!", resultado);
		printMenuFrases();
	}
}

void MenuEstadisticas(ProcesadordeTareas & procesador){
	int option;
	string resultado;
	string op;
	int logout = 0;
	int res_estadistica = 0;
	list<string> lista;
	list<string>::iterator it;
	try{
        while (logout != 1) {
        	printMenuEstadisticas();
        	getline(cin, op);
        	option = get_Opcion(op);
        	switch (option) {
				case 1: //Terminos promedio por frase
					cout << "Aguarde un instante por favor...." << endl;
					res_estadistica = procesador.estadistica_terminos_promedio_por_frase();
					resultado = "";
					resultado.append("(CANTIDAD DE TERMINOS)/(CANTIDAD DE FRASES) = " + Palabra::intToString(res_estadistica) + "\n\n");
					resultado.append("\n");
					resultado.append("OBS: no se consideraron términos repetidos ni palabras del archivo stopwords\n");
					printResultadoOpcion("TERMINOS PROMEDIO POR FRASE", resultado);
					break;
				case 2: //Tasa de fallos
					cout << "Aguarde un instante por favor...." << endl;
					res_estadistica = procesador.estadistica_tasa_de_fallos();
					resultado = "";
					resultado.append("(cantidad_no_encontrados * 100 / cantidad_terminos) = " + Palabra::intToString(res_estadistica) + "%\n\n");
					resultado.append("\n");
					resultado.append("OBS: no se consideraron términos repetidos ni palabras del archivo stopwords\n");
					printResultadoOpcion("TASA DE FALLOS", resultado);
					break;
				case 3: //Lista de no encontrados
					cout << "Aguarde un instante por favor...." << endl;
					lista = procesador.lista_terminos_no_encontrados();
					resultado = "";
					for(it = lista.begin(); it != lista.end(); ++it){
						resultado.append(*it + "\n");
					}
					resultado.append("Cantidad_no_encontrados = " + Palabra::intToString(lista.size()) + "\n\n");
					resultado.append("\n");
					resultado.append("OBS: no se consideraron términos repetidos ni palabras del archivo stopwords\n\n");
					printResultadoOpcion("LISTA DE TERMINOS NO ENCONTRADOS", resultado);
					break;
				case 4: //RANKING
					cout << "Ingrese la cantidad de terminos del ranking" << endl;
					getline(cin, op);
					cout << "Aguarde un instante por favor...." << endl;
					lista = procesador.lista_ranking_terminos_populares(get_Opcion(op));
					resultado = "";
					for(it = lista.begin(); it != lista.end(); ++it){
						resultado.append(*it + "\n");
					}
					resultado.append("Cantidad = " + Palabra::intToString(lista.size()) + "\n\n");
					resultado.append("\n");
					resultado.append("OBS: no se consideraron términos repetidos ni palabras del archivo stopwords\n\n");
					printResultadoOpcion("RANKING DE LOS " + op + " TERMINOS MAS POPULARES", resultado);
					break;
				case 5:
					logout = 1;
					break;
				default:
					break;
        	}
        }
	}catch(exception &e){
		string resultado = "";
		resultado.append("Se produjo un error al procesar su solicitud.");
		resultado.append("\n");
		resultado.append("DESCRIPCION: " + (string)e.what());
		printResultadoOpcion("ATENCION!!!", resultado);
		printMenuFrases();
	}
}

int main(){
	int opcion = 5;
	string op = "";
	int logout = 0;
	int m;
	cout << "Procesando.... por favor aguarde un instante" << endl;
	ProcesadordeTareas procesador("");
	printEstructuraDirectorios();
	limpiarPantalla();

	printEncabezado("ELECCION DEL ARBOL");
    cout << "Elija con que estructura de arbol desea trabajar:" << endl;
    cout << "1 -    DEFAULT    (arbol precargado con todo el diccionario de 70647 términos)" << endl;
    cout << "2 -    NUEVO      (carga desde cero del archivo de terminos ordenados)" << endl;
    cout << "otro - SALIR      (sale de la aplicacion)" << endl;
    cout << '\n';
    cout << " ";
    cout << "Su eleccion: ";

    string strarbol;
    int arbol = 1;
    getline(cin, strarbol);
    arbol = get_Opcion(strarbol);

    switch (arbol) {
		case 1:
			procesador.crear_arbol(true, M_DEFAULT_ARBOL);
			break;
		case 2:
			cout << "ingrese el valor M (M*64 => tamanio del nodo): ";
			cin >> m;
			procesador.crear_arbol(false, m);
			procesador.cargar_arbol_terminos();
			break;
		default:
			logout = 1;
			break;
	}

	while (logout != 1) {
	     printMenuPrincipal();
	     getline(cin, op);
	     opcion=get_Opcion(op);
	     switch (opcion) {
			 case 1:
				 MenuTerminos(procesador);
				 break;
			 case 2:
				 MenuFrases(procesador);
				 break;
			 case 3:
				 MenuEstadisticas(procesador);
				 break;
			 case 4:
				 limpiarPantalla();
				 logout=1;
				 break;
			 default:
				 break;
	     }
	}
	return 0;
}

